package com.dtp.adapter.common;

import com.dtp.common.ApplicationContextHolder;
import com.dtp.common.event.AlarmCheckEvent;
import com.dtp.common.event.CollectEvent;
import com.dtp.common.event.RefreshEvent;
import com.dtp.common.properties.DtpProperties;
import com.dtp.core.handler.CollectorHandler;
import com.dtp.core.notify.manager.AlarmManager;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.GenericApplicationListener;
import org.springframework.core.ResolvableType;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;

import static com.dtp.common.constant.DynamicTpConst.SCHEDULE_NOTIFY_ITEMS;

/**
 * Dtp适配器监听类
 *
 * @author yanhom
 * @since 1.0.6
 *
 * @remark muse
 */
@Slf4j
public class DtpAdapterListener implements GenericApplicationListener {

    /** 只支持RefreshEvent、CollectEvent和AlarmCheckEvent这3种事件 */
    @Override
    public boolean supportsEventType(ResolvableType resolvableType) {
        Class<?> type = resolvableType.getRawClass();
        if (type != null)
            return RefreshEvent.class.isAssignableFrom(type)
                    || CollectEvent.class.isAssignableFrom(type)
                    || AlarmCheckEvent.class.isAssignableFrom(type);
        return false;
    }

    /** 针对不同的响应事件执行不同的操作 */
    @Override
    public void onApplicationEvent(@NonNull ApplicationEvent event) {
        try {
            if (event instanceof RefreshEvent) doRefresh(((RefreshEvent) event).getDtpProperties());
            else if (event instanceof CollectEvent) doCollect(((CollectEvent) event).getDtpProperties());
            else if (event instanceof AlarmCheckEvent) doAlarmCheck(((AlarmCheckEvent) event).getDtpProperties());
        } catch (Exception e) {
            log.error("DynamicTp adapter, event handle failed.", e);
        }
    }

    /** 收集线程池状态的统计信息 */
    protected void doCollect(DtpProperties dtpProperties) {
        val handlerMap = ApplicationContextHolder.getBeansOfType(DtpAdapter.class);
        if (CollectionUtils.isEmpty(handlerMap)) return;

        handlerMap.forEach((k, v) -> v.getMultiPoolStats().forEach(ps -> // DtpAdapter.getMultiPoolStats()
                CollectorHandler.getInstance().collect(ps, dtpProperties.getCollectorTypes())));
    }

    /** 执行刷新操作 */
    protected void doRefresh(DtpProperties dtpProperties) {
        val handlerMap = ApplicationContextHolder.getBeansOfType(DtpAdapter.class);
        if (CollectionUtils.isEmpty(handlerMap)) return;

        handlerMap.forEach((k, v) -> v.refresh(dtpProperties)); // DtpAdapter.refresh(...)
    }

    /** 执行警报检测 */
    protected void doAlarmCheck(DtpProperties dtpProperties) {
        val handlerMap = ApplicationContextHolder.getBeansOfType(DtpAdapter.class);
        if (CollectionUtils.isEmpty(handlerMap)) return;

        handlerMap.forEach((k, v) -> {
            val executorWrapper = v.getExecutorWrappers(); // DtpAdapter.getExecutorWrappers()
            executorWrapper.forEach((kk, vv) -> AlarmManager.doAlarmAsync(vv, SCHEDULE_NOTIFY_ITEMS));
        });
    }
}
